package uk.ac.bbk.dcs.pakdd2014;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;

public class MCLifeProbability implements java.io.Serializable {


	/**
	 * 
	 */
	private static final long serialVersionUID = -7577720149110397147L;
	private int module;
	private int component;
	private HashMap<Integer,Integer> broken;
	private HashMap<Integer,Integer> total;
	private Distribution dist;
	
	private MCLifeProbability(RepairDate rd, SalesDate sd, boolean onlywithsolddate) {
		module=rd.getModule();
		component=rd.getComponent();
		dist = new Distribution();

		broken=new HashMap<Integer,Integer>();
		total=new HashMap<Integer,Integer>();
		Date soldDate;
		Date failureDate;
		Integer broke;
		for(Entry<Date, HashMap<Date, Integer>> entry1: rd.getRepaired().entrySet()){
			soldDate=entry1.getKey();
			if(sd.getSold().containsKey(soldDate)){
				for(Entry<Date, Integer> entry2: entry1.getValue().entrySet()){
					failureDate=entry2.getKey();
					broke=entry2.getValue();
					int life=failureDate.differenceDate(soldDate);
					if(broken.containsKey(life)){
						broken.put(life,broken.get(life)+broke);
					} else broken.put(life,broke);
					
					if(total.containsKey(life)){
						total.put(life,total.get(life)+sd.getSold().get(soldDate));
					} else total.put(life,sd.getSold().get(soldDate));
				}
			}
		}
		
		if(!onlywithsolddate){
			for(Entry<Date, HashMap<Date, Integer>> entry1: rd.getRepaired().entrySet()){
				soldDate=entry1.getKey();
				if(!sd.getSold().containsKey(soldDate)){
					for(Entry<Date, Integer> entry2: entry1.getValue().entrySet()){
						failureDate=entry2.getKey();
						broke=entry2.getValue();
						int life=failureDate.differenceDate(soldDate);
						if(broken.containsKey(life)){
							broken.put(life,broken.get(life)+broke);
						} else broken.put(life,broke);
						
						if(total.containsKey(life)){
							total.put(life,total.get(life)+broke);
						} else total.put(life,broke);
					}
				}
			}
		}
		
		for(int age : total.keySet())
		{
			dist.include(age,probability(age));
		}
	}
	
	public int getModule() {
		return module;
	}

	public int getComponent() {
		return component;
	}

	public HashMap<Integer, Integer> getBroken() {
		return broken;
	}

	public HashMap<Integer, Integer> getTotal() {
		return total;
	}
	
	public double probability(int l){
		if(broken.containsKey(l) && total.containsKey(l))
		{
			return (double)broken.get(l)/(double)total.get(l);
		}
		else
		{
			return 0;
		}
	}

	public double getPrediction(int age)
	{
		return dist.prob(age);
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + component;
		result = prime * result + module;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MCLifeProbability other = (MCLifeProbability) obj;
		if (component != other.component)
			return false;
		if (module != other.module)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "MCLifeProbability [module=" + module + ", component="
				+ component + ", broken=" + broken + ", total=" + total + "]";
	}
	
	public String[][] getPobabilities(){
		String[][] ret=new String[broken.size()][2];
		int index=0;
		for(Entry<Integer,Integer>br:broken.entrySet()){
			ret[index][0]=""+br.getKey();
			ret[index][1]=""+probability(br.getKey());
			index++;
		}
		return ret;
	}
	
	
	public static MCLifeProbability buildMC(RepairDate  rd, SalesDate sd, boolean onlywithsolddate){
		if(rd.getModule()==sd.getModule() && rd.getComponent()==sd.getComponent())
					return new MCLifeProbability(rd, sd, onlywithsolddate);
		return null;
	}
	
	public static HashSet<MCLifeProbability> buildAllMC(HashSet<RepairDate>  rds,HashSet<SalesDate> sds, boolean onlywithsolddate){
		HashSet<MCLifeProbability>ret=new HashSet<MCLifeProbability>();
		for(RepairDate rd: rds)
			for(SalesDate sd: sds) 
				if(rd.getModule()==sd.getModule() && rd.getComponent()==sd.getComponent())
					ret.add(new MCLifeProbability(rd, sd, onlywithsolddate));
		return ret;
	}
	
}
